﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace WordCloudCsharp
{
    /// <summary>
    /// Occupancy Map
    /// </summary>
    public class OccupancyMap : IntegralImage
    {
        private Random Rand { get; set; }

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="outputImgWidth"></param>
        /// <param name="outputImgHeight"></param>
        public OccupancyMap(int outputImgWidth, int outputImgHeight) : base(outputImgWidth, outputImgHeight)
        {
            Rand = new Random(Environment.TickCount);
        }

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="mask"></param>
        public OccupancyMap(Image mask) : base(new FastImage(mask))
        {
            Rand = new Random(Environment.TickCount);
        }


        /// <summary>
        /// get the first availible postion from occupancy map
        /// </summary>
        /// <param name="strSizeX"></param>
        /// <param name="strSizeY"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        /// <remarks>Obsoleted because this methods not brief enough</remarks>
        [Obsolete("TryFindUnoccupiedPosition is deprecated, please use GetRandomUnoccupiedPosition instead.")]
        public bool TryFindUnoccupiedPosition(int strSizeX, int strSizeY, out Point p)
        {
            var startPosX = Rand.Next(1, OutputImgWidth);
            var startPosY = Rand.Next(1, OutputImgHeight);

            int x, y, dx, dy;
            x = y = dx = 0;
            dy = -1;
            var width = OutputImgWidth - strSizeX;
            var height = OutputImgHeight - strSizeY;

            var t = Math.Max(width, height);
            var maxI = t * t;

            for (var i = 0; i < maxI; i++)
            {
                if ((-width / 2 <= x) && (x <= width / 2) && (-height / 2 <= y) && (y <= height / 2))
                {
                    var posX = x + startPosX;
                    var posY = y + startPosY;
                    if (posY > 0 && posY < OutputImgHeight - strSizeY && posX > 0 && posX < OutputImgWidth - strSizeX)
                    {
                        if (GetArea(posX, posY, strSizeX, strSizeY) == 0)
                        {
                            p = new Point(posX, posY);
                            return true;
                        }
                    }
                }
                if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
                {
                    t = dx;
                    dx = -dy;
                    dy = t;
                }
                x += dx;
                y += dy;
            }
            p = new Point();
            return false;
        }

        /// <summary>
        /// get the a random postion from all availible positions from occupancy map
        /// </summary>
        /// <param name="strSizeX"></param>
        /// <param name="strSizeY"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        /// <remarks>Obsoleted because this methods not brief enough</remarks>
        [Obsolete("TryFindRandomUnoccupiedPosition is deprecated, please use GetRandomUnoccupiedPosition instead.")]
        public bool TryFindRandomUnoccupiedPosition(int strSizeX, int strSizeY, out Point p)
        {
            var startPosX = Rand.Next(1, OutputImgWidth);
            var startPosY = Rand.Next(1, OutputImgHeight);

            int x, y, dx, dy;
            x = y = dx = 0;
            dy = -1;
            var width = OutputImgWidth - strSizeX;
            var height = OutputImgHeight - strSizeY;

            var t = Math.Max(width, height);
            var maxI = t * t;

            var posList = new List<Point>();

            for (var i = 0; i < maxI; i++)
            {
                if ((-width / 2 <= x) && (x <= width / 2) && (-height / 2 <= y) && (y <= height / 2))
                {
                    var posX = x + startPosX;
                    var posY = y + startPosY;
                    if (posY > 0 && posY < OutputImgHeight - strSizeY && posX > 0 && posX < OutputImgWidth - strSizeX)
                    {
                        if (GetArea(posX, posY, strSizeX, strSizeY) == 0)
                        {
                            posList.Add(new Point(posX, posY));
                        }
                    }
                }
                if ((x == y) || ((x < 0) && (x == -y)) || ((x > 0) && (x == 1 - y)))
                {
                    t = dx;
                    dx = -dy;
                    dy = t;
                }
                x += dx;
                y += dy;
            }
            if (posList.Count == 0)
            {
                p = new Point();
                return false;
            }
            else
            {
                p = posList[Rand.Next(0, posList.Count - 1)];
                return true;
            }
        }

        /// <summary>
        /// GetRandomUnoccupiedPosition
        /// <para>得到闲置的point</para>
        /// </summary>
        /// <param name="strSizeX"></param>
        /// <param name="strSizeY"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public bool GetRandomUnoccupiedPosition(int strSizeX, int strSizeY, out Point p)
        {
            var posList = new List<Point>();
            for (var i = 1; i < OutputImgWidth - strSizeX; i++)
            {
                for (var j = 1; j < OutputImgHeight - strSizeY; j++)
                {
                    if (GetArea(i, j, strSizeX, strSizeY) == 0)
                    {
                        posList.Add(new Point(i, j));
                    }
                }
            }
            if (posList.Count == 0)
            {
                p = new Point();
                return false;
            }
            else
            {
                var randomIndex = Rand.Next(0, posList.Count - 1);
                p = posList[randomIndex];
                return true;
            }
        }
    }
}
